import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Docs/Helpers/Undo Redo" />

# Undo Redo

---

Out of the box, reaflow supports undo and redo functionality. This can be
done optionally using the `useUndo` hook. It also supports hotkeys using
[reakeys](https://github.com/reaviz/reakeys).

## Getting Started
The `useUndo` hooks will automatically manage the history of the
nodes and edges, all you need to do is manage the current state.
The hook accepts the following arguments:

```ts
export interface UndoProps {
  /**
   * Current node datas.
   */
  nodes: NodeData[];

  /**
   * Current edge datas.
   */
  edges: EdgeData[];

  /**
   * Max history count.
   */
  maxHistory?: number;

  /**
   * Disabled or not.
   */
  disabled?: boolean;

  /**
   * On undo/redo event handler.
   */
  onUndoRedo: (state: UndoRedoEvent) => void;
}
```

To implement the hook all you need to do is import it like:

```tsx
import { useUndo, EdgeData, Canvas, NodeData } from 'reaflow';

const MyApp = () => {
  const [nodes, setNodes] = useState<NodeData[]>([]);
  const [edges, setEdges] = useState<EdgeData[]>([]);

  const { undo, redo, canUndo, canRedo } = useUndo({
    nodes,
    edges,
    onUndoRedo: (state: UndoRedoEvent) => {
      console.log('Undo / Redo', state);
      // Note: This is where YOUR state comes into play
      setEdges(state.edges);
      setNodes(state.nodes);
    }
  });

  return <Canvas nodes={nodes} edges={edges} />;
}
```

The `UndoRedoEvent` interface looks like:

```ts
export interface UndoRedoEvent {
  /**
   * Updated node datas.
   */
  nodes?: NodeData[];

  /**
   * Updated edge datas.
   */
  edges?: EdgeData[];

  /**
   * Type of change.
   */
  type: 'undo' | 'redo' | 'clear';

  /**
   * Whether you can undo now.
   */
  canUndo: boolean;

  /**
   * Whether you can redo now.
   */
  canRedo: boolean;
}
```

Now anytime you make a change to the `nodes` or `edges` the
hook will update the internal history and then you can
call `undo` or `redo` functions to retrieve those states.

The hook returns other properties such as:

```ts
export interface UndoResult {
  /**
   * Can undo or not.
   */
  canUndo: boolean;

  /**
   * Can redo or not.
   */
  canRedo: boolean;

  /**
   * Count of existing changes.
   */
  count: () => number;

  /**
   * Clear state and save first element of new state.
   */
  clear: (nodes: NodeData[]; edges: EdgeData[]) => void;

  /**
   * Get history of state.
   */
  history: () => { nodes: NodeData[]; edges: EdgeData[] }[];

  /**
   * Perform an redo.
   */
  redo: () => void;

  /**
   * Perform a undo.
   */
  undo: () => void;
}
```
